使用场景
A接口 -> B接口 调用失败,重试、重试失败降级处理;
如:实现第三方的app Push推送;
如:消息系统推送消息给订阅方;
pom.xml
项目基于springboot,在根pom.xml中引用,所以这里没有<version>,以springboot中的版本为准;
项目根pom.xml1
2
3
4
5
6<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.4.0.RELEASE</version>
    <relativePath/>
</parent>
项目modepom.xml1
2
3
4
5
6
7
8
9<!-- spring-retry -->
<dependency>
    <groupId>org.springframework.retry</groupId>
    <artifactId>spring-retry</artifactId>
</dependency>
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
</dependency>
spring-retry知识
| 1 | (value= {RemoteAccessException.class},maxAttempts = 3,backoff = (delay = 1000l,multiplier = 1)) | 
- @Retryable- value选择需要重试的异常,可指定多个;- maxAttempts最大重试次数,超过则调用@Recover指定的方法(根据异常类型)- delay每次重试的间隔时间
- @Recover
 当超过重试次数,则调用此注解的方法(根据异常类型)
使用原则:不要全部异常都进行重试,要有选择性的根据异常重试;
两种使用方式
我目前使用的第一种方式,因为业务比较简单;
1、@Retryable和@Recover在同一个类中
@EnableRetry启动配置1
2
3
4
class RetryConfig{
}
业务类RemoteService.java1
2
3
4
5
6
7
8
9
10
11
12
public class RemoteService {
    (value= {RemoteAccessException.class},maxAttempts = 3,backoff = (delay = 1000l,multiplier = 1))
    public void call(String param){
        System.out.println("do something...");
        throw new RemoteAccessException("RPC调用异常");
    }
    
    public void recover(RemoteAccessException e) {
        System.out.println("recover====>"+e.getMessage());
    }
}
约束:
1、@Retryable 和 @Recover必须在同一个类中
2、这个类必须是受spring管理的bean
3、方法必须是public
2、拦截器
@EnableRetry启动配置,且加上拦截器1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
(prefix = "mq.consumer.callback", name = {"retry-times","retry-delay-inMilliseconds"} ,matchIfMissing = false)
public class RetryConfig{
    
    private ConsumerProperties consumerProperties;
    //每一个业务方法对应一个拦截器和自定义recover
    
    (name = "retryInterceptor")
    public RetryOperationsInterceptor retryInterceptor() {
        return RetryInterceptorBuilder
                .stateless().recoverer(new CustomMessageRecover())
                .backOffOptions(0L,1D, consumerProperties.getCallback().getRetryDelayInMilliseconds())
                .maxAttempts(consumerProperties.getCallback().getRetryTimes()).build();
    }
    static class CustomMessageRecover implements MethodInvocationRecoverer<Void> {
        
        public Void recover(Object[] args, Throwable cause) {
            System.out.println("IN THE RECOVER ZONE!!!");
            return null;
        }
    }
}
业务类RemoteService.java1
2
3
4
5
6
7
8
public class RemoteService {
    (value= {RemoteAccessException.class},interceptor = "retryInterceptor")
    public void call(String param){
        System.out.println("do something...");
        throw new RemoteAccessException("RPC调用异常");
    }
}
注意到没?@Recover注解的方法不在里面了;已经由拦截器代理到CustomMessageRecover类